﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HCSAnalyzer.Classes.Base_Classes.DataStructures;
using HCSAnalyzer.Classes.MetaComponents;
using Kitware.VTK;
using System.Windows.Forms;
using System.Drawing;
using ImageAnalysis;
using HCSAnalyzer.Classes.ImageAnalysis._3D_Engine;
using HCSAnalyzer.Classes._3D;
using LibPlateAnalysis;
using HCSAnalyzer.Classes.Base_Classes.GUI;
using HCSAnalyzer.Classes.General_Types;

namespace HCSAnalyzer.Classes.Base_Classes.Viewers
{
    class cViewer3D : cDataDisplay
    {
        public cViewer3D()
        {
            base.Title = "3D Viewer";
        }

        c3DNewWorld Input = null;

        public void SetInputData(c3DNewWorld Input)
        {
            this.Input = Input;
        }

        RenderWindowControl renderWindowControl1;

        public cFeedBackMessage Run()
        {

            renderWindowControl1 = new RenderWindowControl();
            renderWindowControl1.Load += new EventHandler(renderWindowControl1_Load);

            renderWindowControl1.Width = base.CurrentPanel.Width;
            renderWindowControl1.Height = base.CurrentPanel.Height;

            base.CurrentPanel.Title = this.Title;
            base.CurrentPanel.Anchor = (System.Windows.Forms.AnchorStyles)(System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom
                                        | System.Windows.Forms.AnchorStyles.Left
                                        | System.Windows.Forms.AnchorStyles.Right);


            renderWindowControl1.Anchor = (System.Windows.Forms.AnchorStyles)(System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom
                                        | System.Windows.Forms.AnchorStyles.Left
                                        | System.Windows.Forms.AnchorStyles.Right);


            // CurrentPanel.MouseDown += new MouseEventHandler(renderWindowControl1_MouseDown);

            CurrentPanel.Controls.Add(renderWindowControl1);

            return base.FeedBackMessage;
        }
        
        private void _3DObjectProperties_Color(object sender, EventArgs e)
        {
            cObject3D Obj = (cObject3D)((ToolStripMenuItem)sender).Tag;
            if (Obj == null) return;

            ColorDialog ColorPicker = new ColorDialog();
            ColorPicker.Color = Obj.GetColor();
            if (ColorPicker.ShowDialog() != DialogResult.OK) return;
            Obj.SetColor(ColorPicker.Color);
            //renderWindowControl1.Update();
         //   Obj.vtk_Actor.SetDragable(1);
        }

        private void _3DObjectProperties_Scale(object sender, EventArgs e)
        {
            cObject3D Obj = (cObject3D)((ToolStripMenuItem)sender).Tag;

            if (Obj == null) return;
            FormForSingleSlider SliderForOpacity = new FormForSingleSlider("Object Scale");
            SliderForOpacity.numericUpDown.Maximum = 1000;
            SliderForOpacity.numericUpDown.Value = (decimal)(Obj.GetScale() * 100.0);

            if (SliderForOpacity.ShowDialog() != DialogResult.OK) return;

            Obj.SetScale((double)SliderForOpacity.numericUpDown.Value / 100.0);
        }

        private void _3DObjectProperties_Opacity(object sender, EventArgs e)
        {
            cObject3D Obj = (cObject3D)((ToolStripMenuItem)sender).Tag;

            if (Obj == null) return;
            FormForSingleSlider SliderForOpacity = new FormForSingleSlider("Object Opacity");
            SliderForOpacity.numericUpDown.Value = (decimal)(Obj.GetOpacity()*100.0);

            if (SliderForOpacity.ShowDialog() != DialogResult.OK) return;


            Obj.SetOpacity((double)SliderForOpacity.numericUpDown.Value/100.0);
            
            //this.Opacity = (int);
            //RefreshDisplay();

            ////for (int j = 0; j < this.input.Count; j++)
            //foreach (var item in this.Series[0].Points)
            //{
            //    Color C = item.Color;
            //    item.Color = Color.FromArgb(this.Opacity, C);
            //}

        }



        void RenderWindow_RightButtonPressEvt(vtkObject sender, vtkObjectEventArgs e)
        {
            CompleteMenu = new ContextMenuStrip();
            
            ToolStripMenuItem ToolStripMenuItem_World = new ToolStripMenuItem("World");
            ToolStripMenuItem ScaleItem = new ToolStripMenuItem("Scale");
            ToolStripMenuItem_World.DropDownItems.Add(ScaleItem);
            ScaleItem.Click += new System.EventHandler(this.ScaleClicking);


            ToolStripMenuItem ToolStripMenuItem_ChangeBackgroundColor = new ToolStripMenuItem("Background Color");
            ToolStripMenuItem_World.DropDownItems.Add(ToolStripMenuItem_ChangeBackgroundColor);
            ToolStripMenuItem_ChangeBackgroundColor.Click += new System.EventHandler(this.ToolStripMenuItem_ChangeBackgroundColor);

            ToolStripMenuItem ToolStripMenuItem_SaveToImage = new ToolStripMenuItem("Save View");
            ToolStripMenuItem_World.DropDownItems.Add(ToolStripMenuItem_SaveToImage);
            ToolStripMenuItem_SaveToImage.Click += new System.EventHandler(this.ToolStripMenuItem_SaveToImage);

            string MetaObjectName = "";
            int[] Pos= iren.GetEventPosition();
            //vtkPicker Picker = vtkPicker.New();
            vtkPropPicker Pick = vtkPropPicker.New();
            Pick.Pick(Pos[0], Pos[1], 0, Renderer);
            int numActors = Pick.Pick(Pos[0], Pos[1], 0, Renderer);
            
            ToolStripMenuItem TypeItem = null;
           // ToolStripMenuItem ToolStripMenuItem_ObjectDisplay = new ToolStripMenuItem("Object Display");
            ToolStripMenuItem ToolStripMenuItem_DescriptorDisplay = new ToolStripMenuItem("Object Profil"); 

            if (numActors == 1)
            {
                vtkActor PickedActor = Pick.GetActor();

                for (int i = 0; i < this.Input.ListVolume.Count; i++)
                {
                    //if (this.Input.ListVolume[i].vtk_volume == PickedActor)
                    //{
                    //}


                    ToolStripMenuItem ToolStripMenuItem_3DVolumeProperties = new ToolStripMenuItem("3D Volume Properties");

                    cVolumeRendering3D Obj = (cVolumeRendering3D)this.Input.ListVolume[i];

                    Obj.ChangeOpacity(20, 120, 0.01);
                    ToolStripMenuItem _3DVolumeProperties_Opacity = new ToolStripMenuItem("Opacity");
                    _3DVolumeProperties_Opacity.Tag = Obj;
                    ToolStripMenuItem_3DVolumeProperties.DropDownItems.Add(_3DVolumeProperties_Opacity);
                 //   _3DVolumeProperties_Opacity.Click += new System.EventHandler(this._3DObjectProperties_Opacity);

                    CompleteMenu.Items.Add(ToolStripMenuItem_3DVolumeProperties);

                }

                
                for (int i = 0; i < this.Input.ListObject.Count; i++)
                {
                    if (this.Input.ListObject[i].GetActor() == PickedActor)
                    {
                        if (this.Input.ListObject[i].GetType().BaseType.BaseType == typeof(cObject3D))
                        {
                            cObject3D Obj = (cObject3D)this.Input.ListObject[i];

                            ToolStripMenuItem ToolStripMenuItem_3DObjectProperties = new ToolStripMenuItem("3D Object Properties");

                            ToolStripMenuItem _3DObjectProperties_Opacity = new ToolStripMenuItem("Opacity");
                            _3DObjectProperties_Opacity.Tag = Obj;
                            ToolStripMenuItem_3DObjectProperties.DropDownItems.Add(_3DObjectProperties_Opacity);
                            _3DObjectProperties_Opacity.Click += new System.EventHandler(this._3DObjectProperties_Opacity);

                            ToolStripMenuItem _3DObjectProperties_Color = new ToolStripMenuItem("Color");
                            _3DObjectProperties_Color.Tag = Obj;
                            ToolStripMenuItem_3DObjectProperties.DropDownItems.Add(_3DObjectProperties_Color);
                            _3DObjectProperties_Color.Click += new System.EventHandler(this._3DObjectProperties_Color);

                            ToolStripMenuItem _3DObjectProperties_Scale = new ToolStripMenuItem("Scale");
                            _3DObjectProperties_Scale.Tag = Obj;
                            ToolStripMenuItem_3DObjectProperties.DropDownItems.Add(_3DObjectProperties_Scale);
                            _3DObjectProperties_Scale.Click += new System.EventHandler(this._3DObjectProperties_Scale);


                            CompleteMenu.Items.Add(ToolStripMenuItem_3DObjectProperties);
                        }


                        if (this.Input.ListObject[i].GetType().BaseType != typeof(cGeometric3DObject))
                        {
                            cInteractive3DObject Obj = (cInteractive3DObject)this.Input.ListObject[i];
                            if (Obj.GetMetaObjectContainer() != null) MetaObjectName = Obj.GetMetaObjectContainer().Information.GetName() + " -> ";

                            Type T = this.Input.ListObject[i].GetType();
                            List<double> ListDesc = null;
                            List<string> ListProfilName = null;
                            //  ToolStripMenuItem ToolStripMenuItem_SelectedActor = new ToolStripMenuItem(T.ToString()+i);
                            //CompleteMenu.Items.Add(ToolStripMenuItem_SelectedActor);
                            //ToolStripMenuItem_ChangeBackgroundColor.Click += new System.EventHandler(this.ToolStripMenuItem_ChangeBackgroundColor);
                             if (T.Name == "cBiologicalSpot")
                            {
                                cBiologicalSpot TmpSpot = (cBiologicalSpot)this.Input.ListObject[i];
                                ListProfilName = TmpSpot.Information.GetDescriptorNames();
                                ListDesc = TmpSpot.Information.GetInformation();
                                TypeItem = new ToolStripMenuItem(MetaObjectName + TmpSpot.GetType());
                            }

                            if (ListProfilName != null)
                                for (int idxName = 0; idxName < ListDesc.Count; idxName++)
                                {
                                    ToolStripMenuItem descName = new ToolStripMenuItem(ListProfilName[idxName] + " : " + ListDesc[idxName]);
                                    ToolStripMenuItem_DescriptorDisplay.DropDownItems.Add(descName);
                                }
                            else
                            {
                                ToolStripMenuItem descName = new ToolStripMenuItem("Null");
                                ToolStripMenuItem_DescriptorDisplay.DropDownItems.Add(descName);
                            }



                            //  ToolStripMenuItem_ObjectDisplay.DropDownItems.Add(TypeItem);

                            //  CompleteMenu.Items.Add(ToolStripMenuItem_ObjectDisplay);
                            CompleteMenu.Items.Add(ToolStripMenuItem_DescriptorDisplay);

                        }
                        else
                        {
                            cGeometric3DObject Obj = (cGeometric3DObject)this.Input.ListObject[i];


                            if (Obj.ParentTag.GetType() == typeof(cListGeometric3DObject))
                            {
                                CompleteMenu.Items.Add(((cListGeometric3DObject)Obj.ParentTag).GetContextMenu());
                            }
                            //Obj.Tag;                        
                        }

                        if (this.Input.ListObject[i].GetType().BaseType.BaseType == typeof(cObject3D))
                        {
                            cObject3D TmpObj = (cObject3D)this.Input.ListObject[i];
                            if (TmpObj.Tag == null) continue;

                            if(TmpObj.Tag.GetType()==typeof(cWell))
                            {
                                cWell TmpWell = (cWell)(TmpObj.Tag);

                                foreach (var item in TmpWell.GetExtendedContextMenu())
                                    CompleteMenu.Items.Add(item);
                            }
                            else if (TmpObj.Tag.GetType() == typeof(cDescriptorType))
                            {
                                cDescriptorType TmpDesc = (cDescriptorType)(TmpObj.Tag);

                                foreach (var item in TmpDesc.GetExtendedContextMenu())
                                    CompleteMenu.Items.Add(item);

                            
                            }

                        }


                        break;
                    }

                }
            }

            CompleteMenu.Items.Add(ToolStripMenuItem_World);

            //ToolStripMenuItem ToolStripMenuItem_DisplayElevationMap = new ToolStripMenuItem("Display Elevation Map");
            //CompleteMenu.Items.Add(ToolStripMenuItem_DisplayElevationMap);
            //ToolStripMenuItem_DisplayElevationMap.Click += new System.EventHandler(this.DisplayElevationMap);


            //#region display options

            //ToolStripMenuItem ToolStripMenuItem_DisplayOptions = new ToolStripMenuItem("Display options");
            //CompleteMenu.Items.Add(ToolStripMenuItem_DisplayOptions);

            //this.ToolStripMenuItem_DisplayOptionsDispValues = new ToolStripMenuItem("Display values");
            //ToolStripMenuItem_DisplayOptionsDispValues.CheckOnClick = true;
            //ToolStripMenuItem_DisplayOptionsDispValues.Checked = this.IsDisplayValues;
            //ToolStripMenuItem_DisplayOptions.DropDownItems.Add(ToolStripMenuItem_DisplayOptionsDispValues);
            //ToolStripMenuItem_DisplayOptionsDispValues.Click += new System.EventHandler(this.ToolStripMenuItem_DisplayOptionsDisValues);

            //#endregion


            CompleteMenu.Show(Control.MousePosition);
        }

        vtkRenderWindowInteractor iren;

        private void RenderWindow_KeyPressEvt(vtkObject sender, vtkObjectEventArgs e)
        {
            sbyte KeyCode = this.iren.GetKeyCode();

            int AltK = this.iren.GetAltKey();
            int CtrlK = this.iren.GetControlKey();

            //> >>        s = self.iren.GetShiftKey()
            //> >>        kc = self.iren.GetKeyCode()
            //> >>        ks = self.iren.GetKeySym()

            if (KeyCode ==103)
            {
                foreach (var item in this.Input.ListObject)
                {
                    if (item.ObjectType == "Geometrical")
                            item.vtk_Actor.GetProperty().SetOpacity(1);
                }
            }
            if (KeyCode == 98)
            {
                foreach (var item in this.Input.ListObject)
                {
                    if (item.ObjectType == "Geometrical")
                        item.vtk_Actor.GetProperty().SetOpacity(0);
                }
            }
            if (KeyCode ==104)
            {
                foreach (var item in this.Input.ListObject)
                {
                    if (item.ObjectType != "Geometrical")
                            item.vtk_Actor.GetProperty().SetOpacity(1);
                }
            }
            if (KeyCode == 110)
            {
                foreach (var item in this.Input.ListObject)
                {
                    if (item.ObjectType != "Geometrical")
                        item.vtk_Actor.GetProperty().SetOpacity(0);
                }
            }
            if (KeyCode == 106)
            {
                foreach (var item in this.Input.ListVolume)
                {
                    item.vtk_volume.VisibilityOn();
                }
            }
            if (KeyCode == 109)
            {
                foreach (var item in this.Input.ListVolume)
                {
                    item.vtk_volume.VisibilityOff();
                }
            }
            if (KeyCode == 45)
            {
                foreach (var item in this.Input.ListObject)
                {
                    if (item.ObjectType == "Geometrical") continue;
                    double CurrentOpacity = item.vtk_Actor.GetProperty().GetOpacity() - 0.01;
                    if (CurrentOpacity < 0.01) CurrentOpacity = 0.01;
                    item.vtk_Actor.GetProperty().SetOpacity(CurrentOpacity);
                }
                //renWin.Render();
            }

            if (KeyCode == 43)
            {
                foreach (var item in this.Input.ListObject)
                {
                    if (item.ObjectType == "Geometrical") continue;
                    double CurrentOpacity = item.vtk_Actor.GetProperty().GetOpacity() + 0.01;
                    if (CurrentOpacity > 1) CurrentOpacity = 1;
                    item.vtk_Actor.GetProperty().SetOpacity(CurrentOpacity);
                }
                //renWin.Render();
            }

            //if (KeyCode == 119)
            //{
            //    foreach (var item in this.Input.ListObject)
            //    {
            //        if (item.ObjectType == "Geometrical") continue;
            //        item.vtk_Actor.GetProperty().SetRepresentationToWireframe();
            //    }
            //}

            //if (KeyCode == 115)
            //{
            //    foreach (var item in this.Input.ListObject)
            //    {
            //        if (item.ObjectType == "Geometrical") continue;
            //        item.vtk_Actor.GetProperty().SetRepresentationToSurface();
            //    }
            //}

            base.CurrentPanel.Refresh();
        }

        vtkLegendScaleActor legendScaleActor = null;

        private void ScaleClicking(object sender, EventArgs e)
        {
            if (this.legendScaleActor == null)
            {
                legendScaleActor = vtkLegendScaleActor.New();
                Renderer.AddActor(legendScaleActor);
                this.legendScaleActor.SetVisibility(1);
            }
            else
            {

                if (this.legendScaleActor.GetVisibility() == 0)
                    this.legendScaleActor.SetVisibility(1);
                else
                    this.legendScaleActor.SetVisibility(0);
            }

            base.CurrentPanel.Refresh();
        }

        private void ToolStripMenuItem_ChangeBackgroundColor(object sender, EventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            if (colorDialog.ShowDialog() != DialogResult.OK) return;
            Color BackGroundColor = colorDialog.Color;

            Renderer.SetBackground(BackGroundColor.R / 255.0, BackGroundColor.G / 255.0, BackGroundColor.B / 255.0);

            base.CurrentPanel.Refresh();

        }
 
        private void ToolStripMenuItem_SaveToImage(object sender, EventArgs e)
        {
            SaveFileDialog SaveFileDialogCurrScene = new SaveFileDialog();
            SaveFileDialogCurrScene.OverwritePrompt = true;
            SaveFileDialogCurrScene.AutoUpgradeEnabled = true;
            SaveFileDialogCurrScene.Filter = "TIFF files (*.tiff)|*.tiff";
            DialogResult result = SaveFileDialogCurrScene.ShowDialog();
            if (result != DialogResult.OK) return;

            string FileName = SaveFileDialogCurrScene.FileName;

            vtkWindowToImageFilter W2i = vtkWindowToImageFilter.New();
            W2i.SetInput(renderWindowControl1.RenderWindow);
            W2i.Update();

            vtkTIFFWriter TIFFWriter = vtkTIFFWriter.New();
            TIFFWriter.SetInputConnection(W2i.GetOutputPort());
            TIFFWriter.SetFileName(FileName);
            TIFFWriter.Write();

        }

        private void renderWindowControl1_Load(object sender, EventArgs e)
        {
            try
            {
                GenerateGraph();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK);
            }
        }

        vtkRenderer Renderer;
        //vtkRenderWindow RenderWindow;

        private void GenerateGraph()
        {
            // get a reference to the renderwindow of our renderWindowControl1
            vtkRenderWindow RenderWindow = renderWindowControl1.RenderWindow;


            //renWin = vtkRenderWindow.New();
            RenderWindow.LineSmoothingOn();
            RenderWindow.PointSmoothingOn();
            //  RenderWindow.SetWindowName("3D World");
            // RenderWindow.BordersOn();
            RenderWindow.DoubleBufferOn();
            //RenderWindow.SetSize(WinPos[0], WinPos[1]);

            //this.ren1 = vtkRenderer.New();

            // this.Input.renWin = RenderWindow;

            Renderer = RenderWindow.GetRenderers().GetFirstRenderer();

            foreach (var item in this.Input.ListObject)
            {
                item.AddMeToTheWorld(Renderer);
            }
            foreach (var item in this.Input.ListVolume)
            {
                item.AddMeToTheWorld(Renderer);
            }

            RenderWindow.AddRenderer(Renderer);

            iren = new vtkRenderWindowInteractor();
            iren.SetRenderWindow(RenderWindow);

            // iren.SetInteractorStyle(vtkInteractorStyleJoystickCamera.New());
            iren.SetInteractorStyle(vtkInteractorStyleTrackballCamera.New());
            //   iren.SetInteractorStyle(vtkInteractorStyleTerrain.New());


            // iren.LeftButtonPressEvt += new vtkObject.vtkObjectEventHandler(RenderWindow_LeftButtonPressEvt);
            iren.KeyPressEvt += new vtkObject.vtkObjectEventHandler(RenderWindow_KeyPressEvt);
            iren.RightButtonPressEvt += new vtkObject.vtkObjectEventHandler(RenderWindow_RightButtonPressEvt);

            Renderer.SetBackground(this.Input.BackGroundColor.R / 255.0, this.Input.BackGroundColor.G / 255.0, this.Input.BackGroundColor.B / 255.0);
            
            Renderer.SetActiveCamera(this.Input.Vtk_CameraView);

            
            
            
            //Renderer.ResetCamera();

           // Input.Render();

        }
    }
}
